import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:joy_ui/joy_ui.dart';

const _kActionDuration = 500;

class InAppMessageGuide extends StatefulWidget {
  final List<Key> introKeys;
  InAppMessageGuide({
    this.introKeys,
  });
  @override
  _InAppMessageGuideState createState() => _InAppMessageGuideState();
}

class _InAppMessageGuideState extends State<InAppMessageGuide> {
  IntroItem _introItem;

  @override
  void initState() {
    super.initState();
    if (!mounted) return;
    _updateIntro();
  }

  @override
  Widget build(BuildContext context) {
    final colorPalette = getColorPalette(context);
    return Material(
      elevation: 3,
      color: colorPalette.persistentDarkSurface(),
      clipBehavior: Clip.hardEdge,
      child: CustomPaint(
        child: Stack(
          children: [
            Positioned(
              top: _introItem.rectangle.top,
              left: _introItem.rectangle.left,
              child: InkWell(
                child: Container(
                  width: _introItem.rectangle.width,
                  height: _introItem.rectangle.height,
                  decoration: BoxDecoration(
                    color: Colors.transparent,
                    border: Border.all(),
                    borderRadius: BorderRadius.circular(5.0),
                  ),
                ),
                onTap: _introItem.action,
              ),
            ),
          ],
        ),
        painter: _BackgroundPainter(target: null),
        foregroundPainter: _ForegroundPainter(),
      ),
    );
  }

  IntroItem getIntroItemBy(Key key) {
    VoidCallback action;
    Rectangle rectangle;
    var element = elementOf(key);
    rectangle = rectangleOf(element);
    var introWidget = element.widget;
    if (introWidget is JoyButton) {
      action = () {
        introWidget.onPressed();
      };
    }
    return IntroItem(
      rectangle: rectangle,
      action: action,
    );
  }

  Element elementOf(Key key) {
    context.visitChildElements((element) {
      if (element.widget.key == key) {
        return element;
      }
    });
    return null;
  }

  Rectangle rectangleOf(Element element) {
    Size size;
    Offset origin;
    if (element.renderObject is RenderBox) {
      var box = element.renderObject as RenderBox;
      origin = box.localToGlobal(Offset.zero);
      size = box.size;
    }
    return Rectangle(origin.dx, origin.dy, size.width, size.height);
  }

  void _updateIntro() {
    Future.delayed(
      Duration(milliseconds: _kActionDuration),
      () {
        SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
          setState(() {
            _introItem = getIntroItemBy(
              widget.introKeys.removeLast(),
            );
          });
        });
      },
    );
  }
}

class IntroItem {
  final Rectangle rectangle;
  final VoidCallback action;

  IntroItem({
    this.rectangle,
    this.action,
  });
}

class _BackgroundPainter extends CustomPainter {
  final Rectangle target;
  _BackgroundPainter({
    @required this.target,
  });

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()..color = Colors.grey.withOpacity(0.4);
    canvas.drawPaint(paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

class _ForegroundPainter extends CustomPainter {
  final Rectangle target;

  _ForegroundPainter({this.target});
  @override
  void paint(Canvas canvas, Size size) {
    var centerY = target.top + target.height * 0.5;
    var centerX = target.left + target.width * 0.5;
    if (centerY < size.height * 0.5) {}
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

/*
1. inappmessage -> introduce guide

2. -> selectTab

3. -> scrollToTp

4. -> select navigator to subpage button

5. -> select action1

6. -> select action2 ...

7. -> skip guide 

**/
